﻿using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Data;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories;

namespace EcoSystem
{
    public class NotificationAppService : CrudAppService<
        Notification,
        NotificationDto,
        Guid,
        GetNotificationInput,
        CreateOrUpdateNotificationDto,
        CreateOrUpdateNotificationDto>, INotificationAppService
    {
        public NotificationAppService(IRepository<Notification, Guid> repository) : base(repository)
        {

        }

        public async Task<List<NotificationDto>> CreateManyAsync(List<CreateOrUpdateNotificationDto> input)
        {
            var items = new List<Notification>();
            foreach (var item in input)
            {
                var entity = MapToEntity(item);
                EntityHelper.TrySetId(entity, () => GuidGenerator.Create());
                items.Add(entity);
            }
            await Repository.InsertManyAsync(items);
            return ObjectMapper.Map<List<Notification>, List<NotificationDto>>(items);
        }

        public override Task<NotificationDto> GetAsync(Guid id)
        {
            return base.GetAsync(id);
        }

        public override async Task<PagedResultDto<NotificationDto>> GetListAsync(GetNotificationInput input)
        {
            var query = (await Repository.GetQueryableAsync()).AsNoTracking()
                 .Where(x => x.UserId == CurrentUser.Id)
                 .WhereIf(input.IsRead.HasValue, x => x.IsRead == input.IsRead)
                 .WhereIf(input.StartTime.HasValue, x => x.CreationTime > DateTime.Now);
            var total = await query.CountAsync();
            var items = await query.OrderByDescending(x => x.Id).PageBy(input).ToListAsync();
            return new PagedResultDto<NotificationDto>()
            {
                Items = await MapToGetListOutputDtosAsync(items),
                TotalCount = total
            };
        }

        public async Task<List<NotificationDto>> GetAllListAsync(GetNotificationInput input)
        {
            var query = (await Repository.GetQueryableAsync()).AsNoTracking()
                .Where(x => x.UserId == CurrentUser.Id)
                .WhereIf(input.IsRead.HasValue, x => x.IsRead == input.IsRead)
                .WhereIf(input.StartTime.HasValue, x => x.CreationTime > DateTime.Now);
            var items = await query.OrderByDescending(x => x.Id).ToListAsync();
            return await MapToGetListOutputDtosAsync(items);
        }

        public async Task SetReadAsync(Guid id)
        {
            var query = await Repository.GetQueryableAsync();
            query = query.Where(x => x.Id == id && x.UserId == CurrentUser.Id);
            await query.ExecuteUpdateAsync(b => b.SetProperty(x => x.IsRead, x => true));
        }

        public async Task<int> ReadAllAsync()
        {
            var query = await Repository.GetQueryableAsync();
            query = query.Where(x => x.UserId == CurrentUser.Id && x.IsRead == true);
            return await query.ExecuteUpdateAsync(b => b.SetProperty(x => x.IsRead, x => true));
        }

        public async Task<int> ClearAllAsync()
        {
            var query = await Repository.GetQueryableAsync();
            query = query.Where(x => x.UserId == CurrentUser.Id);
            return await query.ExecuteDeleteAsync();
        }
    }
}
